﻿using Prism.Commands;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using ViewModelBase = Com.Lancetinc.Evs.ViewModels.ViewModelBase;

namespace Com.Lancetinc.Evs.Controls
{
    /// <summary>
    /// 分页控件
    /// </summary>
    public partial class PaginationControl : INotifyPropertyChanged
    {
        public event EventHandler<int> CurrentPageChanged;

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as PaginationControl)?.RefreshLayout();
        }

        #region PageSize

        public static readonly DependencyProperty PageSizeProperty
            = DependencyProperty.Register(nameof(PageSize),
                typeof(int),
                typeof(PaginationControl),
                new PropertyMetadata(20, OnPropertyChanged));

        /// <summary>
        /// 每页显示条目个数，支持
        /// </summary>
        public int PageSize
        {
            get => (int)this.GetValue(PageSizeProperty);
            set => this.SetValue(PageSizeProperty, value);
        }

        #endregion

        #region TotalCount

        public static readonly DependencyProperty TotalCountProperty
            = DependencyProperty.Register(nameof(TotalCount),
                typeof(int),
                typeof(PaginationControl),
                new PropertyMetadata(0, OnPropertyChanged));

        /// <summary>
        /// 总条目数
        /// </summary>
        public int TotalCount
        {
            get => (int)this.GetValue(TotalCountProperty);
            set => this.SetValue(TotalCountProperty, value);
        }

        #endregion

        #region CurrentPageNo

        public static readonly DependencyProperty CurrentPageNoProperty
            = DependencyProperty.Register(nameof(CurrentPageNo),
                typeof(int),
                typeof(PaginationControl),
                new PropertyMetadata(0, (d, e) =>
                {
                    var self = d as PaginationControl;
                    if (self == null) return;
                    OnPropertyChanged(d, e);
                    self.CurrentPageChanged?.Invoke(self, (int)e.NewValue);
                }));

        /// <summary>
        /// 当前所在页
        /// </summary>
        public int CurrentPageNo
        {
            get => (int)this.GetValue(CurrentPageNoProperty);
            set => this.SetValue(CurrentPageNoProperty, value);
        }

        #endregion

        private int TotalPage => (int)Math.Ceiling(TotalCount * 1.0 / PageSize);

        public ICommand PageClickCommand { get; }

        public DelegateCommand<string> GoPreviousNextCommand { get; }

        private readonly DelegateCommand _goFirstPageCommand;
        private readonly DelegateCommand _goLastPageCommand;
        public ICommand GoFirstPageCommand => _goFirstPageCommand;
        public ICommand GoLastPageCommand => _goLastPageCommand;

        public PaginationControl()
        {
            InitializeComponent();
            PageClickCommand = new DelegateCommand<PageItemViewModel>(ExecutePageClick);
            GoPreviousNextCommand = new DelegateCommand<string>(ExecuteGoPreviousNext, CanExecuteGoPreviousNext);
            _goFirstPageCommand = new DelegateCommand(ExecuteGoFirstPage, CanExecuteGoFirstPage);
            _goLastPageCommand = new DelegateCommand(ExecuteGoLastPage, CanExecuteGoLastPage);
            this.DataContext = this;
            BtnPrevious.Command = GoPreviousNextCommand;
            BtnNext.Command = GoPreviousNextCommand;
        }

        #region Commands

        private bool CanExecuteGoFirstPage()
        {
            return TotalPage > 1 && CurrentPageNo > 1;
        }

        private void ExecuteGoFirstPage()
        {
            CurrentPageNo = 1;
        }

        private bool CanExecuteGoLastPage()
        {
            return TotalPage > 1 && CurrentPageNo < TotalPage;
        }

        private void ExecuteGoLastPage()
        {
            CurrentPageNo = TotalPage;
        }

        private bool CanExecuteGoPreviousNext(string isPrev)
        {
            var totalPage = TotalPage;
            if (isPrev == "1")
                return totalPage > 1 && CurrentPageNo > 1;
            else
                return totalPage > 1 && CurrentPageNo < totalPage;
        }

        private void ExecuteGoPreviousNext(string isFirst)
        {
            if (isFirst == "1")
            {
                if (CurrentPageNo > 1)
                    --CurrentPageNo;
            }
            else
            {
                if (CurrentPageNo < TotalPage)
                    ++CurrentPageNo;
            }
        }

        private void ExecutePageClick(PageItemViewModel vm)
        {
            if (!vm.IsClickAble)
                return;

            this.CurrentPageNo = vm.PageNo;
        }

        private void RefreshButtonState()
        {
            GoPreviousNextCommand.RaiseCanExecuteChanged();
            _goFirstPageCommand.RaiseCanExecuteChanged();
            _goLastPageCommand.RaiseCanExecuteChanged();
        }
        #endregion
        // 如果页数很多的话，选中页加上左右两边显示的页的数量,奇数
        // [1] [...] [10] [11] [☑️12)] [13] [14] [...] [100]
        private const int PagerCount = 5;
        private readonly IList<PageItemViewModel> _items = new ObservableCollection<PageItemViewModel>();
        private void RefreshLayout()
        {
            _items.Clear();
            // 总页数
            int totalPage = (int)Math.Ceiling(TotalCount * 1.0 / PageSize);
            if (totalPage <= PagerCount + 2)
            {
                totalPage = Math.Max(totalPage, 1); // 至少需要1页
                for (int i = 0; i < totalPage; i++)
                {
                    var pageNo = i + 1;
                    var vm = CreatePageItemViewModel(pageNo, CurrentPageNo, totalPage);
                    _items.Add(vm);
                }
            }
            else
            {
                var pageNos = CalcVisiblePageNo(CurrentPageNo, totalPage);
                foreach (var pageNo in pageNos)
                {
                    var vm = CreatePageItemViewModel(pageNo, CurrentPageNo, totalPage);
                    _items.Add(vm);
                }
            }

            RefreshButtonState();
            if (IcPages.ItemsSource == null)
                IcPages.ItemsSource = _items;
        }

        private PageItemViewModel CreatePageItemViewModel(int pageNo, int currentPageNo, int totalPage)
        {
            var isDot = pageNo < 0;
            var no = isDot ? 0 : pageNo;
            return new PageItemViewModel
            {
                PageNo = no,
                Text = isDot ? "..." : pageNo.ToString(),
                IsFirst = pageNo == 1,
                IsLast = pageNo == totalPage,
                IsClickAble = !isDot || totalPage <= 1,
                IsSelected = pageNo == currentPageNo
            };
        }

        /// <summary>
        /// 计算可点击的页
        /// 其中包含小于0的项，表示[...]
        /// </summary>
        /// <param name="currentPageNo"></param>
        /// <param name="totalPage"></param>
        /// <returns></returns>
        private int[] CalcVisiblePageNo(int currentPageNo, int totalPage)
        {
            if (currentPageNo < PagerCount)
            {
                var pagingList = Enumerable.Range(1, PagerCount + 1).ToList();
                if (!pagingList.Contains(totalPage))
                {
                    pagingList.AddRange(new[] { int.MinValue, totalPage });
                }
                return pagingList.ToArray();
            }

            if (currentPageNo > totalPage - PagerCount + 1)
            {
                var pagingList = Enumerable.Range(totalPage - PagerCount, PagerCount + 1).ToList();
                if (!pagingList.Contains(1))
                {
                    pagingList.InsertRange(0, new[] { 1, int.MinValue });
                }
                return pagingList.ToArray();
            }

            {
                var pagingAry = Enumerable.Range(currentPageNo - ((PagerCount - 1) / 2), PagerCount).ToList();
                var pagingList = new List<int>();
                pagingList.Add(1);
                pagingList.Add(int.MinValue);
                pagingList.AddRange(pagingAry);
                pagingList.Add(int.MinValue);
                pagingList.Add(totalPage);
                return pagingList.ToArray();
            }
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        #endregion
    }

    class PageItemViewModel : ViewModelBase
    {
        private int _pageNo;

        public int PageNo
        {
            get => _pageNo;
            set => SetProperty(ref _pageNo, value);
        }

        private string _text;

        public string Text
        {
            get => _text;
            set => SetProperty(ref _text, value);
        }

        /// <summary>
        /// 是否可点击？
        /// </summary>
        public bool IsClickAble { get; set; } = true;

        private bool _isSelected;

        public bool IsSelected
        {
            get => _isSelected;
            set => SetProperty(ref _isSelected, value);
        }

        private bool _isFirst;

        public bool IsFirst
        {
            get => _isFirst;
            set => SetProperty(ref _isFirst, value);
        }

        private bool _isLast;

        public bool IsLast
        {
            get => _isLast;
            set => SetProperty(ref _isLast, value);
        }
    }
}
